#Copyright (c) 2012-8 Civa Lin. All rights reserved.
"""
Parse Utility 文字分析工具模組

本模組提供字串工具，處理某些特殊的純文字。

本模組的變數命名方式：
    filename 表示完整檔案路徑
    dir 或 dirname 表示路徑
    base 表示主檔名
    ext 表示副檔名（含.）
    baseext 表示 base + ext
"""

import re
import html.parser as HP

class NotMatch(Exception): pass

_body = re.compile(r'<\s*?body.*?>(.*?)<\s*?/\s*?body\s*?>',
        flags = re.DOTALL) # 記得匹配換行符
_body_fuzzy = re.compile(r'<\s*?body.*?>(.*)',
        flags = re.DOTALL) # 將開始標籤後的內容全部取出

def html2content(html):
    '''將 html 去頭去尾，只留下 body 內側的部份

        如果無法找到完整的 body 元素，則儘可能不錯失地切割出 body
        無法找到切割點的情況下，會直接傳回原值。
        '''
    try:
        return _body.search(html).group(1)
    except:
        try:
            return _body_fuzzy.search(html).group(1)
        except:
            return html

_newline = re.compile(r'\n+')
_need_newline = re.compile( # 都是end標籤，包括p br h1~6 li
    r'(<\s*?/\s*?li\s*?>|<\s*?/\s*?p\s*?>|<\s*?br\s*?/\s*?>|<\s*?/\s*?h[1-6]\s*?>)')
_tag = re.compile(r'<[^>]*>')

class ToText(HP.HTMLParser):
    '''將Html轉換成純文字，並且合理地換行'''
    def __init__(self):
        super().__init__()
        self.invisible_tag = {'head', 'script', 'object', 'javascript', 'iframe', 'video', 'audio'}
        self.start_newline_tag = {'br', 'hr', 'pre', 'div','blockquote',
                'h1', 'h2', 'h3', 'h4', 'h5', 'h6'}
        self.end_newline_tag = {'pre', 'li', 'p', 'div', 'blockquote',
                'h1', 'h2', 'h3', 'h4', 'h5', 'h6'}
        self.indent_tag = {'ul', 'ol', 'blockquote'}
        # 資料儲藏點
        self.datas = []
        # 狀態訊息
        self.in_pre = 0
        self.in_invisible = 0
        self.in_indent_level = 0
    def handle_starttag(self, tag, attrs):
        # pre 開始偵測
        if tag == 'pre':
            self.in_pre += 1
        # 看不見開始偵測
        if tag in self.invisible_tag:
            self.in_invisible += 1
        if tag in self.indent_tag:
            self.in_indent_level += 1
        # 需換行偵測
        if tag in self.start_newline_tag:
            self.datas.append('\n')
    def handle_endtag(self, tag):
        # pre 閉合偵測
        if tag == 'pre' and self.in_pre >= 1:
            self.in_pre -= 1
        # 看不見閉合偵測
        if tag in self.invisible_tag and self.in_invisible >= 1:
            self.in_invisible -= 1
        if tag in self.indent_tag and self.in_indent_level >= 1:
            self.in_indent_level -= 1
        # 需換行偵測
        if tag in self.end_newline_tag:
            self.datas.append('\n')
    def handle_data(self, data):
        if self.in_invisible <= 0: # 要是看不見當然不用匯入
            if self.in_pre <= 0:
                data = data.replace('\n', '')
            if self.in_indent_level >= 1:
                self.datas.append(' ' * 4 * self.in_indent_level)
            self.datas.append(data)
    def reset(self):
        super().reset()
        self.datas = []
    def feed(self, data):
        super().feed(data)
        ans = ''.join(self.datas)
        ans = HP.HTMLParser().unescape(ans)
        self.reset()
        return ans

to_text_parser = ToText()

def html2txt(html):
    '''將 html 內文去掉標籤並轉為純文字

        html   = 含有 html 內容的字串
        return ==> 純文字字串
        '''
    return to_text_parser.feed(html)
    # new = html2content(html) # 擷取 body 部份，其他拋棄
    # # new = _newline.sub(r'', new) # 先剃掉所有現有的換行符號
    # # new = _need_newline.sub(r'\1\n\n', new)# 在某些標籤尾端補上換行符號
    # new = _tag.sub(r'', new)  # 剃掉所有 html 標籤
    # new = HP.HTMLParser().unescape(new) # unescape
    # return new

